/**
 * @author YinHang
 * 基于jQuery的工具库.
 * 最后修改时使用的jQuery版本: 1.4.3.
 */
(function ($) {
	//包结构
	$.extend({
		util: {
			view: {
				PageInfo: PageInfo,
				Paging: Paging
			},
			Data: {
				request: request
			},
			paramsToObj: paramsToObj,
			loading: loading,
			cancelLoading: cancelLoading,
			selectJoint: selectJoint,
			mergeUnnamedObj: mergeUnnamedObj,
			mergeUnnamedJson: mergeUnnamedJson,
			hasClass: hasClass,
			toCharCodesForHTML: toCharCodesForHTML,
			getValue: getValue,
			toXmlDom: toXmlDom,
			xmlDomSelector: xmlDomSelector
		}
	});
	
	function getValue(obj, vstr, defaultValue, trueValue) {
		if(!defaultValue)
			defaultValue = "&nbsp;";
		var value;
		try{
			eval("value = obj." + vstr + ";");
		} catch(e) {
			return defaultValue;
		}
		if(trueValue)
			return value;
		else
		{
			return (value || value == 0) ? value : defaultValue;
		}
	};
	
	function toCharCodesForHTML(str) {
		var charCodes = [];
		for(var i = 0;i<str.length;++i)
			charCodes.push("&#" + str.charCodeAt(i) + ";");
		return charCodes.join("");
	};
	
	function hasClass(obj, className) {
		var $obj = $(obj);
		if(!$obj || $obj.size() <= 0)
			return false;
		var classes = $(obj).attr("class").split(" ");
		return $.inArray(className, classes) != -1;
	};
	
	/**
	 * 合并未命名的对象/数组
	 * @param nos
	 * @return
	 */
	function mergeUnnamedObj(nos) {
		var newObj = {};
		for(var name in nos)
			newObj[name] = nos[name];
		return newObj;
	};
	
	/**
	 * 将多个为命名的json字符串分别转换为对象,并合并成一个hashlist.
	 */
	function mergeUnnamedJson(nos) {
		var newObj = {};
		for(var name in nos)
			newObj[name] = $.parseJSON(nos[name]);
		return newObj;
	};
	
	/**
	 * select: select
	 * child: childSelect
	 * url: action
	 * idName: idName
	 * valueName: valueName,
	 * postIdName: postIdName
	 */
	function selectJoint(params)
	{
		var $select = $(params.select);
		var $childSelect = $(params.child);
		function update() {
			$childSelect.attr("disabled", "disabled");
			var id = $(this).val();
			var postParams = {};
			postParams[params.postIdName] = id;
			request({
				buffer: true,
				saveKey: id,
				url: params.url,
				data: postParams,
				dataType: "json",
				type: "post",
				success: function (data) {
					var list = data.relationTaskList;
					var length = list.length;
					$childSelect.empty();
					for(var i=0;i<length;++i)
						$childSelect.append("<option value='" + list[i].dataValueId + "'>" + list[i].value + "</option>");
					$childSelect.removeAttr("disabled");
				}
			});
		};
		update.apply(params.select);
		$select.bind("change", update);
	};
	
	//进度条
	var loading = 0;
	var loadingBar = null;
	function loading() {
		if(!loadingBar)
		{
			loadingBar = $("<div id='loadingBar'>请稍后...</div>").appendTo(document.body);
			if($.browser.msie)
			{
				loadingBar.css("position", "absolute");
				function adjust() {
					var $document = $(document);
					var $window = $(window);
					var offset = {top:  $document.scrollTop() + $window.height() - 28, left: $document.scrollLeft() + $window.width() - 87};
					loadingBar.position(offset);
				};
				adjust();
				$(window).bind("scroll", function () {
					adjust();
				}).bind("resize", function () {
					adjust();
				});
			}
			loadingBar.hide();
		}
		if(++ loading > 0)
		{
			$("#loadingBar").show();
		}
	};
	
	function cancelLoading() {
		if(-- loading <= 0)
			$("#loadingBar").hide();
	};
	
	function xmlDomSelector(xmlDom, selector) {
		var nodeNameList = selector.split(" ");
		var nodeNameListLen = nodeNameList.length;
		var resultList = [];
		var parents = [xmlDom];
		for(var i=0;i<nodeNameListLen;++i)
			parents = findNodes(parents, nodeNameList[i]);
		return parents;
	};
	
	function findNodes(parents, nodeName) {
		var parentsNum = parents.length;
		var resultList = [];
		for(var i=0;i<parentsNum;++i)
		{
			var foundNodes = parents[i].getElementsByTagName(nodeName);
			var foundNum = foundNodes.length;
			for(var i=0;i<foundNum;++i)
				resultList.push(foundNodes[i]);
		}
		return resultList;
	};
	
	function toXmlDom(xmlStr) {
		var xmlDom;
		if(window.DOMParser)
			xmlDom = new DOMParser().parseFromString(xmlStr, "text/xml");
		else	
		{
			xmlDom = new ActiveXObject("Microsoft.XMLDOM");
			xmlDom.async = "false";
			xmlDom.loadXML(xmlStr);
		}
		return xmlDom;
	};
	
	function request(params) 
	{
		if(params.buffer == true)
		{
			var key = "$request_buffer@" + params.url + "_" + ( params.saveKey ? params.saveKey : $.param(params.data || {}) );
			var data = _MEM_DATA.data(key);
			if(data)
			{
				if(params.success)
					params.success(data);
				return;
			}
			var _success = params.success;
			params.success = function (data) {
				_MEM_DATA.data(key, data);
				if(_success)
					_success(data);
			};
		}
		if(params.buffer == false)
			_MEM_DATA.removeData(key);
		$.ajax(params);
	};
	
	function paramsToObj(params) 
	{
		if(Object.prototype.toString.apply(params) == "[object String]")
		{
			var newParams = {};
			var tempParams = params.split("&");
			for(var i=0;i<tempParams.length;++i)
			{
				var kv = tempParams[i].split("=");
				if(newParams[kv[0]])
				{
					if($.isArray(newParams[kv[0]]))
						newParams[kv[0]].push(kv[1]);
					else
					{
						var tmp = newParams[kv[0]];
						newParams[kv[0]] = [tmp, kv[1]];
					}
				}
				else
				{
					newParams[kv[0]] = kv[1];
				}
			}
			return newParams;
		}
		return params;
	};
	
	function PageInfo(pageSize, recordCount) 
	{
		this.reset(pageSize, recordCount);
	};
	
	PageInfo.prototype.reset = function (pageSize, recordCount) 
	{
		this.recordCount = recordCount;
		this.firstResult = 0;
		this.pageSize = pageSize;
		this.currentPage = 1;
		this.maxPage = recordCount / pageSize;
		var parsedMaxPage = parseInt(this.maxPage);
		this.maxPage = (parsedMaxPage == this.maxPage) ? this.maxPage : parsedMaxPage + 1;
	};
	
	PageInfo.prototype.nextPage = function () {
		if(this.currentPage < this.maxPage)
		{
			this.firstResult += this.pageSize;
			return ++ this.currentPage;
		}
		return false;
	};
	
	PageInfo.prototype.prevPage = function () {
		if(this.currentPage > 1)
		{
			this.firstResult -= this.pageSize;
			return -- this.currentPage;
		}
		return false;
	};
	
	PageInfo.prototype.setPageSize = function (pageSize) {
		this.pageSize = pageSize;
	};
	
	PageInfo.prototype.setPage = function (page, init) {
		this.currentPage = page;
		this.firstResult = (this.currentPage -1) * this.pageSize;
		return this.currentPage;
	};
	
	PageInfo.prototype.firstPage = function () {
		return this.setPage(1);
	};
	
	PageInfo.prototype.lastPage = function () {
		return this.setPage(this.maxPage);
	};
	//pageSize: 初始化页面大小.
	//updateMethod: 更新函数.
	//pageSizeJsonName.
	//recordCountJsonName.
	//postPageName.
	//postPageSizeName.
	function Paging(params)
	{
		this.pageSize = params.pageSize ? params.pageSize : 10;
		this.pageInfo = new PageInfo(this.pageSize, this.pageSize * 2);
		this.updateMethod = params.updateMethod;
		this.success = params.success;
		this.pageSizeJsonName = params.pageSizeJsonName ? params.pageSizeJsonName : "pageSize";
		this.recordCountJsonName = params.recordCountJsonName ? params.recordCountJsonName : "recordCount";
		this.postPageName = params.postPageName ? params.postPageName : "page";
		this.postPageSizeName = params.postPageSizeName ? params.postPageSizeName : "pageSize";
		this.actions = [];
		this.requestMethod = params.requestMethod ? params.requestMethod : "get";
		this.curAction = "";
	};
	
	//setting.url.
	//setting.params.
	//setting.error.
	Paging.prototype.createAction = function (actionName, setting) {
		if(setting.params)
		{
			if(Object.prototype.toString.apply(setting.params) == "[object String]")
				setting.params = paramsToObj(setting.params);
		}
		this.actions[actionName] = setting;
	};
	
	Paging.prototype.transform = function (actionName) {
		this.curAction = actionName;
	};
	
	Paging.prototype.getCurAction = function () {
		return this.actions[this.curAction];
	};
	
	Paging.prototype.getCurActionName = function () {
		return this.curAction;
	};
	
	Paging.prototype.setParams = function (params, rewrite) {
		var actionParams = this.getCurAction().params;
		for(var key in actionParams)
		{
			if(rewrite)
				actionParams[key] = params[key];
			else if(params[key])
				actionParams[key] = params[key];
		}	
	};
	
	Paging.prototype.deleteParam = function (name) {
		delete this.getCurAction().params[name];
	};
	
	Paging.prototype.resetAllParam = function () {
		var beRemovedParams = this.getCurAction().params;
		for(var key in beRemovedParams)
		{
			this.deleteParam(key);
		}
	};
	
	Paging.prototype.addParams = function (params) {
		if(Object.prototype.toString.apply(params) == "[object String]")
			params = paramsToObj(params);
		$.extend(this.getCurAction().params, params);
	};
	
	Paging.prototype.setParam = function (name, value) {
		this.getCurAction().params[name] = value;
	};
	
	Paging.prototype.setUpdateMethod = function (updateMethod) {
		this.updateMethod = updateMethod;
	};
	
	Paging.prototype.setPageSize = function (pageSize) {
		this.pageInfo.reset(pageSize, pageSize * 2);
	};
	
	Paging.prototype.nextPage = function () {
		if(this.pageInfo.nextPage() == false)
			return false;
		this.updateData(this.getCurAction().error);
	};
	
	Paging.prototype.prevPage = function () {
		if(this.pageInfo.prevPage() == false)
			return false;
		this.updateData(this.getCurAction().error);
	};
	
	Paging.prototype.setPage = function (page) {
		if(this.pageInfo.setPage(page) == false)
			return false;
		this.updateData(this.getCurAction().error);
	};
	
	Paging.prototype.firstPage = function () {
		if(this.pageInfo.firstPage() == false)
			return false;
		this.updateData(this.getCurAction().error);
	};
	
	Paging.prototype.lastPage = function () {
		if(this.pageInfo.lastPage() == false)
			return false;
		this.updateData(this.getCurAction().error);
	};
	
	Paging.prototype.updateData = function () {
		var host = this;
		var params = {};
		params[this.postPageName] = host.pageInfo.currentPage;
		params[this.postPageSizeName] = host.pageInfo.pageSize;
		$.extend(params, host.getCurAction().params);
		//clean param
		for(var paramName in params)
			if(!params[paramName] || params[paramName].length <= 0)
				delete params[paramName];
		//
		request({
			url: host.getCurAction().url,
			dataType: "json",
			type: host.requestMethod ? host.requestMethod : "get",
			data: params,
			async: false,
			success: function (data) {
				if(host.success)
				{
					if(!host.success(data))
						return false;
				}
				var page = host.pageInfo.currentPage;
				host.pageInfo = new PageInfo(eval("data." + host.pageSizeJsonName), eval("data." + host.recordCountJsonName));
				host.pageInfo.setPage(page);
				$.extend(data, {
					_pageSize: host.pageInfo.pageSize - 1
				});
				host.updateMethod.call(host, data);
			},
			error: host.getCurAction().error,
			traditional: true
		});
	};
	
	var _MEM_DATA = $({});
})(jQuery);